package bean;

import java.util.List;
import java.util.Vector;

import common.BeanUtils;

public class Vehicle extends DeepCopy<Vehicle> implements Runnable {
	private static final long serialVersionUID = -4209353744042736284L;
	public static final int LEFT=1,CENTER=2,RIGHT=3;
	public static List<Vehicle> ves;
	private Point next;
	private int type;
	private float speed;
	private Point current;
	private Point start;
	private Point end;
	private Object isMoving;
	public Object finished = false;
	public long startTime = 0;
	public long finishTime = 0;
	/**
	 * lane车道
	 * |← | ↑ | →|
	 * | ↑ | ↑ | ↑ |
	 * |   |   |   |
	 * | 1 | 2 | 3 |
	 */
	public int lane=0;
	public static final boolean DEBUG = true;
	public static final boolean TEST = true;
	/**
	 * path 表示起点到终点所要走的路径
	 * 
	 */
	private List<Point> path;
	/**
	 * passed 表示已经走过的点
	 */
	private List<Point> passed;
	private long id;

	public Vehicle(int id, int type, float speed, Point start, Point end) {
		this.id = id;
		this.type = type;
		this.speed = speed;
		this.start = start;
		this.current = start.deepCopy();
		this.end = end;
		this.isMoving = false;
		this.passed = new Vector<Point>();
		this.path = new Vector<Point>();
		if (ves == null) {
			ves = new Vector<Vehicle>();
		}
		ves.add(this);

	}

	public long getId() {
		return id;
	}

	public int getType() {
		return type;
	}

	public float getSpeed() {
		return speed;
	}

	public Point getCurrent() {
		return current;
	}

	public void setCurrent(Point current) {
		this.current = current;
	}

	public Point getStart() {
		return start;
	}

	public Point getEnd() {
		return end;
	}

	public Object isMoving() {
		return isMoving;
	}

	public Point getNext() {
		return next;
	}

	public List<Point> getPath() {
		return path;
	}

	public void setPath(List<Point> path) {
		this.path=path;
		this.end = this.path.get(this.path.size() - 1).deepCopy();
	}

	public List<Point> getPassed() {
		return passed;
	}

	public void setPassed(List<Point> passed) {
		this.passed = passed;
	}

	public void run() {
		// 随机睡眠0~1000ms，避免发车时在同一点
		try {
			Thread.sleep((long) Math.random() * 1000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		startTime = System.currentTimeMillis();
		while (!(this.current.getX() == this.end.getX() && this.current.getY() == this.end
				.getY())) {
			this.next = this.path.get(this.path.indexOf(this.current) + 1)
					.deepCopy();
			try {
				move();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		finishTime = System.currentTimeMillis();
		synchronized (finished) {
			finished = true;
		}
		if (DEBUG) {
			System.out.println("***Vehicle-" + id + " fineshed***");
			System.out.println("finished in " + (finishTime - startTime)
					+ " milli seconds");
		}
		isMoving = false;
		return;
	}

	/**
	 * 检查其他车辆是不是停在当前车辆即将到达的点上
	 * 
	 * @return
	 */
	private boolean nextClear() {
		for (Vehicle v : ves) {
			if (v.getId() != this.getId()) {
				if (v.getCurrent().equals(this.next)) {
					if (v.isMoving().equals(false) && v.finished.equals(false)) {
						System.out.println("***Vehicle " + v.getId()
								+ " stop before Vehicle " + this.id + "***");
						return false;
					}
				}
			}
		}
		return true;
	}

	private void move() throws InterruptedException {
		if (nextClear()) {
			if (DEBUG) {
				/*System.out.println(id + " move from |---"
						+ this.current.getId() + "(" + this.current.getX()
						+ "," + this.current.getY() + ")--->to--->"
						+ this.next.getId() + "(" + this.next.getX() + ","
						+ this.next.getY() + ")");*/
			}
			this.isMoving = true;
			Thread.sleep(Math.round(BeanUtils.hypot(this.current, this.next)
					/ this.speed * 1000));
			this.passed.add(this.current.deepCopy());
			// 如果此时前端有请求，此时current==next，所以前端会显示finished但是又未真正完成
			this.current = this.next.deepCopy();
		} else {
			this.isMoving = false;
			if (DEBUG) {
				System.out
						.println(id + " is going to sleep few millis seconds");
			}
			Thread.sleep((long) Math.random() * 2000 + 100);
		}
	}

}
